#!/usr/bin/env python

import pypvm
import os
import sys
from sys import stdout
from time import sleep
from ini import *

def buscame_el_mejor_resultado(datos):
    limite = len(datos)
    maximo = datos[0][0]
    for i in datos:
        if i[0] >= maximo:
            maximo = i
    return maximo


def minimax_paralelo(esclavos, tablero, jugador, prof_limite, prof_actual):
    """ minimax_paralelo, que lindo """
    bandera = 0 # esto es si es que no hay sucesores
    retornos = [] # aqui se guardaran los resultados transitorios
    if(prof_limite <= prof_actual or terminal_test(tablero)):
        return (utility(tablero), 0)
    else:
        sucesores = realizar_jugada(tablero, jugador)
        cantidad_de_esclavos = len(esclavos)
        cantidad_de_llamadas = 0
        indice_esclavo_actual = 0
        print 'Cantidad de sucesores'
        print len(sucesores)
        for i in sucesores:
            pypvm.initsend(pypvm.data['default']) # se prepara para enviar
            bandera = 1
            #resultado = -1.0e350#infinito
            nuevotablero = [[], [], [], [], [], [], [], []]
            clonar_tablero(tablero, nuevotablero)
            make_move(nuevotablero, jugador, {i:sucesor.get(i)})
            #se hace la llamada
            data = {'tablero':nuevotablero, 'jugador':jugador*-1, 'prof_limite':prof_limite, 'prof_actual':prof_actual+1}
            pypvm.pk(data) # empaqueta
            esclavo = esclavos[indice_esclavo_actual]
            print ("MASTER: sending data to tid %s..." % esclavo)
            pypvm.send(esclavo, 1)
            cantidad_de_llamadas += 1
            indice_esclavo_actual = (indice_esclavo_actual + 1)  % cantidad_de_esclavos
            if ((cantidad_de_llamadas % cantidad_de_esclavos) == 0):
                # paramos la mano un rato hasta que devuelvan los esclavos
                for sender in esclavos:
                    print("MASTER: receiving data to tid %s..." % sender)
                    pypvm.recv(sender, 2)
                    print "MASTER: data received :D"
                    aux = (pypvm.upk()[0], i)
                    retornos.append(aux)
                    print retornos
                    
        if (bandera == 1):
            # vemos si es que tenemos que esperar mas mensajes de los esclavos
            if ((cantidad_de_llamadas % cantidad_de_esclavos) != 0):
                print 'esclavo_actual'
                print indice_esclavo_actual
                indice_esclavo_actual = (indice_esclavo_actual - 1)  % cantidad_de_esclavos
                print 'esclavo_actual modificado'
                print indice_esclavo_actual
                while (indice_esclavo_actual < cantidad_de_esclavos-1):
                    print("MASTER: receiving data to tid %s..." % esclavos[indice_esclavo_actual])
                    pypvm.recv(esclavos[indice_esclavo_actual], 2)
                    print "MASTER: data received XS"
                    aux = (pypvm.upk()[0], i)
                    retornos.append(aux)
                    print retornos
                    indice_esclavo_actual += 1
                    print 'while'
                    print 'esclavo actual < cantidad de esclavos'
                    print indice_esclavo_actual, '<', cantidad_de_esclavos-1
            # Aqui debemos comparar los resultados
            return buscame_el_mejor_resultado(retornos)
        else:
            resultado=-1.0e350#infinito
            i = 0
            return (resultado, i)
    return buscame_el_mejor_resultado(retornos)


try:
    print "MASTER: setting catchout to stdout..."
    pypvm.catchout(stdout)

    print "MASTER: spawning 2 tasks(esclavo_local_2.py)..."
    slave_file = os.getcwd() + "/esclavo_local_2.py"
    
    tids = pypvm.spawn(slave_file, [], pypvm.spawnOpts['TaskDefault'], "", 2)
    print "MASTER: spawned task's tid = %s" % tids

    print "MASTER: asking for notification on child exits..."
    pypvm.notify(pypvm.notifyDict['TaskExit'], 2, tids, 1)

    print "MASTER: initializing message buffer to PvmDataDefault..."
    pypvm.initsend(pypvm.data['default'])

#    data = ["Soy de Cerro", "Soy del Ciclon", "Vengo de Bo. Obrero"]
#    print("MASTER: packing %s..." % data)
#    pypvm.pk(data)

#    for recipient in tids:
#        print("MASTER: sending data to tid %s..." % recipient)
#        pypvm.send(recipient, 1)

    # aqui empieza el juego
    
    # inicializando
    turno=-1
    tablero = [[0 for i in range(8)] for i in range(8)]
    for i in range(0,8):
        for j in range(0,8):
            tablero[i][j] = 0
    tablero[3][3] = 1
    tablero[3][4] = -1
    tablero[4][3] = -1
    tablero[4][4] = 1
    
    # let's play...
    while(not terminal_test(tablero)):        
        sucesor = realizar_jugada(tablero, turno)
        if (sucesor):
            if(turno==-1):
                print 'Negras'
                movimiento = minimax_paralelo(tids, tablero, -1, 3, 0)
                print "Movimiento"
                print movimiento
                print movimiento[1][0]+1, imprimir_coordenadas (movimiento[1][1])
                pivotes = legal_moves(tablero, -1, movimiento[1][0], movimiento[1][1])
                make_move(tablero, -1, {movimiento[1]:pivotes})
                turno*= -1
                imprimir_tablero(tablero)
                #raw_input()
            else:
                print 'Blancas'
                movimiento = minimax_paralelo(tids, tablero, 1, 3, 0)
                print "Movimiento"
                print movimiento
                print movimiento[1][0]+1, imprimir_coordenadas (movimiento[1][1])
                pivotes = legal_moves(tablero, 1, movimiento[1][0], movimiento[1][1])
                make_move(tablero, 1, {movimiento[1]:pivotes})
                turno*= -1
                imprimir_tablero(tablero)
                #raw_input()
        else:
            print 'HOLA2'
            turno*= -1

    contar_fichas(tablero)

    #print "MASTER: sleeping for 2 seconds (so slaves can catch up)..."
    #sleep(2)
    
    #print "MASTER: sending SIGTERM to children..."
    #for tid in tids:
    #    pypvm.sendsig(tid, SIGTERM)

#    print "MASTER: calling nrecv ()..."
#    pypvm.nrecv (tids[0], 1)

#    results = [None, None]
#    i = 0
#    for sender in tids:
#        print("MASTER: receiving data to tid %s..." % sender)
#        pypvm.recv(sender, 2)
#        results[i] = pypvm.upk()
#        i += 1

#    print "MASTER: printing results from slaves..."
#    print results

    print "MASTER: killing slaves..."
    for tid in tids:
        pypvm.kill(tid)
        
    for tid in tids:
        pypvm.recv(-1, 2)
        print "MASTER: received an exit notification..."

    print "MASTER: exiting pvm..."
    pypvm.exit()

except:
    print "A pypvm error occured!"
    a =  sys.exc_info()
    print str(a[0])
    print a[1]
